/*
 *   Copyright 2012-present OSBI Ltd
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

// Packages
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { isEmpty } from 'lodash';
import {
  Drawer,
  Switch
  // Transfer
} from 'antd';
import Transfer from 'react-virtualized-transfer';
import { Button, Intent } from '@blueprintjs/core';
import { Grid, Row, Col } from 'react-flexbox-grid';
import TruncateString from 'react-truncate-string';

// Services
import { MemberService } from '../../../../../services';

// UI
import { ErrorMessage, Loading } from '../../../../UI';

// Utils
import { Settings } from '../../../../../utils';
import { FILTER } from '../../../../../utils/constants';

// Styles
import 'react-virtualized-transfer/css/transfer.css';
import './SelectMembers.css';

// Constants
const ERROR_MSG = 'Error fetching members';
const INCLUSION = 'INCLUSION';
const EXCLUSION = 'EXCLUSION';

class SelectMembers extends Component {
  _isMounted = false;

  state = {
    availableMembers: [],
    selectedMembers: [],
    useResultOption: Settings.MEMBERS_FROM_RESULT,
    membersLimit: Settings.MEMBERS_LIMIT,
    selectionType: INCLUSION,
    isSelectionType: true,
    isShowUniqueName: false,
    loading: true,
    error: false,
    errorMsg: ERROR_MSG
  };

  componentWillMount() {
    const { hierarchyGroup, level } = this.props;
    const axis = hierarchyGroup.source.draggableId;

    if (axis === FILTER) {
      this.setState({ useResultOption: false });
    }

    if (
      hierarchyGroup &&
      hierarchyGroup.hierarchy &&
      hierarchyGroup.hierarchy.levels.hasOwnProperty(level) &&
      hierarchyGroup.hierarchy.levels[level].hasOwnProperty('selection') &&
      hierarchyGroup.hierarchy.levels[level].selection.hasOwnProperty('members')
    ) {
      const { members, type } = hierarchyGroup.hierarchy.levels[
        level
      ].selection;

      this.setState({
        selectedMembers: members.map(member => member.uniqueName),
        selectionType: type,
        isSelectionType: type === INCLUSION
      });
    }
  }

  componentDidMount() {
    this._isMounted = true;
    this.callApiGetMembers();
  }

  componentWillUnmount() {
    this._isMounted = false;
    MemberService.cancelRequest();
  }

  callApiGetMembers = () => {
    const { queryUuid, hierarchyGroup, level } = this.props;
    const { useResultOption, membersLimit } = this.state;
    const hierarchy = hierarchyGroup.hierarchy.name;

    this.setState({
      loading: true,
      error: false
    });

    MemberService.getMembers({
      uuid: queryUuid,
      hierarchy,
      level,
      result: useResultOption,
      searchlimit: membersLimit
    })
      .then(res => {
        if (this._isMounted && res.status === 200) {
          const { data } = res;

          this.setState({
            availableMembers: this.getMembers(data),
            loading: false
          });
        } else {
          if (this._isMounted) {
            this.setState({
              loading: false,
              error: true
            });
          }
        }
      })
      .catch(error => {
        if (this._isMounted) {
          this.setState({
            loading: false,
            error: true
          });
        }
      });
  };

  getMembers(members) {
    return members.map(member => ({
      key: member.uniqueName,
      title: member.name || member.caption,
      description: member.uniqueName,
      disabled: false
    }));
  }

  handleChange = selectedMembers => {
    this.setState({ selectedMembers });
  };

  triggerSelectionType = isSelectionType => {
    this.setState({
      selectionType: isSelectionType ? INCLUSION : EXCLUSION,
      isSelectionType
    });
  };

  triggerShowUniqueName = isShowUniqueName => {
    this.setState({ isShowUniqueName });
  };

  handleSave = () => {
    const { level, setMembers, onClose } = this.props;
    const { availableMembers, selectedMembers, selectionType } = this.state;
    const newSelectedMembers = [];
    let members = [];

    if (!isEmpty(selectedMembers)) {
      [members] = selectedMembers.map(key => {
        availableMembers.some(member => {
          if (member.key === key) {
            newSelectedMembers.push({
              uniqueName: member.key,
              caption: member.title
            });

            return true;
          }

          return false;
        });

        return newSelectedMembers;
      });
    }

    const selections = { type: selectionType, members };

    setMembers(level, selections);
    onClose();
  };

  renderTransferMembers() {
    const {
      availableMembers,
      selectedMembers,
      isSelectionType,
      isShowUniqueName
    } = this.state;

    return (
      <Grid fluid>
        <Row>
          <Col className="center-block" xs>
            <div className="sku-select-members-container">
              <Row>
                <Col xs>
                  <span className="sku-available-members">
                    Available members:
                  </span>
                </Col>
                <Col xs>
                  <div className="sku-used-members">
                    <span>Used members:</span>
                    <Switch
                      unCheckedChildren="Exclude"
                      checkedChildren="Include"
                      checked={isSelectionType}
                      onChange={this.triggerSelectionType}
                      style={{ marginLeft: 5, marginBottom: 5 }}
                    />
                  </div>
                </Col>
              </Row>
            </div>
          </Col>
        </Row>
        <Row>
          <Col xs>
            {/*
            <Transfer
              className="sku-transfer-members"
              dataSource={availableMembers}
              targetKeys={selectedMembers}
              onChange={this.handleChange}
              render={item =>
                !isShowUniqueName ? item.title : item.description
              }
              lazy
            />
            */}

            <Transfer
              className="sku-transfer-members"
              rowHeight={32}
              dataSource={availableMembers}
              targetKeys={selectedMembers}
              onChange={this.handleChange}
              render={item =>
                !isShowUniqueName ? item.title : item.description
              }
            />
          </Col>
        </Row>
        <Row>
          <Col className="center-block" xs>
            <div className="sku-select-members-container">
              <Row>
                <Col xs>
                  <Switch
                    unCheckedChildren="Show Unique Names"
                    checkedChildren="Hide Unique Names"
                    checked={isShowUniqueName}
                    onChange={this.triggerShowUniqueName}
                    style={{ marginTop: 20 }}
                  />
                </Col>
              </Row>
            </div>
          </Col>
        </Row>
      </Grid>
    );
  }

  render() {
    const { level, visible, onClose } = this.props;
    const { loading, error, errorMsg } = this.state;

    return (
      <Drawer
        className="sku-select-members"
        title={<TruncateString text={`Selections for ${level}`} />}
        width="100%"
        onClose={onClose}
        visible={visible}
        zIndex={2002}
      >
        {loading ? (
          <Loading size={25} text="Fetching members..." center />
        ) : error ? (
          <ErrorMessage text={errorMsg} callApi={this.callApiGetMembers} />
        ) : (
          this.renderTransferMembers()
        )}

        <div
          style={{
            position: 'absolute',
            bottom: 0,
            width: '100%',
            borderTop: '1px solid #e8e8e8',
            padding: '10px 16px',
            textAlign: 'right',
            left: 0,
            background: '#fff'
          }}
        >
          <Button
            text="Save"
            intent={Intent.DANGER}
            style={{
              marginRight: 8
            }}
            onClick={this.handleSave}
          />
          <Button text="Close" onClick={onClose} />
        </div>
      </Drawer>
    );
  }
}

SelectMembers.propTypes = {
  queryUuid: PropTypes.string.isRequired,
  hierarchyGroup: PropTypes.object.isRequired,
  level: PropTypes.string.isRequired,
  visible: PropTypes.bool.isRequired,
  setMembers: PropTypes.func.isRequired,
  onClose: PropTypes.func.isRequired
};

const mapStateToProps = state => ({
  queryUuid: state.query.query.name
});

export default connect(mapStateToProps)(SelectMembers);
